import struct


def calculate_crc16(data):
    """计算Modbus CRC16校验码"""
    crc = 0xFFFF
    for byte in data:
        crc ^= byte
        for _ in range(8):
            if crc & 0x0001:
                crc = (crc >> 1) ^ 0xA001
            else:
                crc >>= 1
    return crc


def is_modbus_data(data):
    """判断数据是否为Modbus RTU格式"""
    if len(data) < 4:
        return False

    try:
        # 检查基本格式
        slave_id = data[0]
        function_code = data[1]

        # 设备地址通常在1-247范围内，0和248-255为特殊用途
        if slave_id == 0 or slave_id > 247:
            return False

        # 检查功能码是否为常见的Modbus功能码
        valid_function_codes = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0F, 0x10, 0x15, 0x16, 0x17]
        if function_code not in valid_function_codes:
            return False

        # 检查CRC校验
        if len(data) >= 4:
            received_crc = struct.unpack('<H', data[-2:])[0]
            calculated_crc = calculate_crc16(data[:-2])
            if received_crc != calculated_crc:
                return False

        # 检查数据长度是否合理
        if function_code in [0x01, 0x02, 0x03, 0x04]:  # 读取功能
            if len(data) >= 5:
                byte_count = data[2]
                expected_length = 3 + byte_count + 2  # 地址+功能码+字节数+数据+CRC
                if len(data) != expected_length:
                    return False
        elif function_code in [0x05, 0x06]:  # 写单个
            if len(data) != 8:  # 固定8字节
                return False
        elif function_code in [0x0F, 0x10]:  # 写多个
            if len(data) >= 9:
                byte_count = data[6]
                expected_length = 7 + byte_count + 2
                if len(data) != expected_length:
                    return False

        return True

    except Exception:
        return False


def parse_modbus_rtu(data):
    """解析Modbus RTU数据包"""
    if len(data) < 4:
        return {"error": "数据包太短，无法解析"}

    try:
        # 基本格式：设备地址(1) + 功能码(1) + 数据(N) + CRC(2)
        slave_id = data[0]
        function_code = data[1]

        # 检查CRC
        if len(data) >= 4:
            received_crc = struct.unpack('<H', data[-2:])[0]  # 小端序
            calculated_crc = calculate_crc16(data[:-2])
            crc_valid = received_crc == calculated_crc
        else:
            crc_valid = False
            received_crc = 0
            calculated_crc = 0

        result = {
            "slave_id": slave_id,
            "function_code": function_code,
            "data_length": len(data),
            "crc_valid": crc_valid,
            "received_crc": f"0x{received_crc:04X}",
            "calculated_crc": f"0x{calculated_crc:04X}",
            "raw_data": data.hex().upper()
        }

        # 根据功能码解析数据
        if function_code == 0x01:  # 读取线圈状态
            result["function"] = "读取线圈状态"
            if len(data) >= 5:
                byte_count = data[2]
                coil_data = data[3:3 + byte_count]
                result["byte_count"] = byte_count
                result["coil_data"] = [hex(b) for b in coil_data]

        elif function_code == 0x02:  # 读取离散输入
            result["function"] = "读取离散输入"
            if len(data) >= 5:
                byte_count = data[2]
                input_data = data[3:3 + byte_count]
                result["byte_count"] = byte_count
                result["input_data"] = [hex(b) for b in input_data]

        elif function_code == 0x03:  # 读取保持寄存器
            result["function"] = "读取保持寄存器"
            if len(data) >= 5:
                byte_count = data[2]
                register_data = data[3:3 + byte_count]
                result["byte_count"] = byte_count

                # 解析寄存器值（每个寄存器2字节，大端序）
                registers = []
                for i in range(0, len(register_data), 2):
                    if i + 1 < len(register_data):
                        reg_value = struct.unpack('>H', register_data[i:i + 2])[0]
                        registers.append(reg_value)
                result["registers"] = registers
                result["register_hex"] = [f"0x{reg:04X}" for reg in registers]

        elif function_code == 0x04:  # 读取输入寄存器
            result["function"] = "读取输入寄存器"
            if len(data) >= 5:
                byte_count = data[2]
                register_data = data[3:3 + byte_count]
                result["byte_count"] = byte_count

                # 解析寄存器值
                registers = []
                for i in range(0, len(register_data), 2):
                    if i + 1 < len(register_data):
                        reg_value = struct.unpack('>H', register_data[i:i + 2])[0]
                        registers.append(reg_value)
                result["registers"] = registers
                result["register_hex"] = [f"0x{reg:04X}" for reg in registers]

        elif function_code == 0x05:  # 写单个线圈
            result["function"] = "写单个线圈"
            if len(data) >= 6:
                coil_address = struct.unpack('>H', data[2:4])[0]
                coil_value = struct.unpack('>H', data[4:6])[0]
                result["coil_address"] = coil_address
                result["coil_value"] = "ON" if coil_value == 0xFF00 else "OFF"

        elif function_code == 0x06:  # 写单个寄存器
            result["function"] = "写单个寄存器"
            if len(data) >= 6:
                register_address = struct.unpack('>H', data[2:4])[0]
                register_value = struct.unpack('>H', data[4:6])[0]
                result["register_address"] = register_address
                result["register_value"] = register_value
                result["register_value_hex"] = f"0x{register_value:04X}"

        elif function_code == 0x0F:  # 写多个线圈
            result["function"] = "写多个线圈"
            if len(data) >= 7:
                start_address = struct.unpack('>H', data[2:4])[0]
                quantity = struct.unpack('>H', data[4:6])[0]
                byte_count = data[6]
                result["start_address"] = start_address
                result["quantity"] = quantity
                result["byte_count"] = byte_count

        elif function_code == 0x10:  # 写多个寄存器
            result["function"] = "写多个寄存器"
            if len(data) >= 7:
                start_address = struct.unpack('>H', data[2:4])[0]
                quantity = struct.unpack('>H', data[4:6])[0]
                byte_count = data[6]
                result["start_address"] = start_address
                result["quantity"] = quantity
                result["byte_count"] = byte_count

        else:
            result["function"] = f"未知功能码 0x{function_code:02X}"

        return result

    except Exception as e:
        return {"error": f"解析错误: {str(e)}"}